/*
 *    Copyright © OpenAtom Foundation.
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */

package com.inspur.edp.bef.dtgenerator.core.rtgen.entitygen.entityimpl;

import com.inspur.edp.bef.bizentity.GspBizEntityObject;
import com.inspur.edp.bef.bizentity.operation.BizAction;
import com.inspur.edp.bef.component.ICompParameter;
import com.inspur.edp.bef.component.detailcmpentity.be.BEComponent;
import com.inspur.edp.bef.component.detailcmpentity.be.BEMethod;
import com.inspur.edp.bef.component.detailcmpentity.be.BEMethodParameter;
import com.inspur.edp.bef.dtgenerator.common.Utils;
import com.inspur.edp.bef.dtgenerator.core.BefCoreGenCtx;
import com.inspur.edp.caf.generator.baseInfo.ParameterInfo;
import com.inspur.edp.caf.generator.baseInfo.TypeInfo;
import com.inspur.edp.caf.generator.method.ClassMethodGenerator;
import com.inspur.edp.lcm.metadata.api.entity.GspMetadata;
import java.util.ArrayList;
import org.eclipse.jdt.core.dom.Block;
import org.eclipse.jdt.core.dom.ClassInstanceCreation;
import org.eclipse.jdt.core.dom.MethodInvocation;
import org.eclipse.jdt.core.dom.Modifier;
import org.eclipse.jdt.core.dom.ReturnStatement;
import org.eclipse.jdt.core.dom.StringLiteral;
import org.eclipse.jdt.core.dom.VariableDeclarationFragment;
import org.eclipse.jdt.core.dom.VariableDeclarationStatement;

public class BEImplMethodGenerator extends ClassMethodGenerator {

  private static final String actionIdentifierName = "action";
  private BefEntityImplGenCtx coreGenContext;
  private BizAction action;
  private BEComponent cmp;
  private BEMethod method;
  private GspBizEntityObject belongObject;
  private ArrayList<ParameterInfo> parList;

  public BEImplMethodGenerator(
      BefEntityImplGenCtx coreGenContext, BizAction action, GspBizEntityObject belongObject) {
    this.coreGenContext = coreGenContext;
    this.action = action;
    this.belongObject = belongObject;
  }

  @Override
  protected Block buildMethodBody() {
    Block block = ast.newBlock();

    if (belongObject.getIsRootNode()) {
      buildCheckAuthStatement(block);
    }
    buildNewActionInfo(block);
    buildExecuteInfo(block);
    return block;
  }

  //	this.getBEContext().checkDataAuthority("Audit");
  private void buildCheckAuthStatement(Block block) {
    MethodInvocation methodInvocation = ast.newMethodInvocation();
    methodInvocation.setName(ast.newSimpleName("checkDataAuthority"));
    StringLiteral stringLiteral = ast.newStringLiteral();
    stringLiteral.setLiteralValue(action.getCode());
    methodInvocation.arguments().add(stringLiteral);

    MethodInvocation methodInvocation1 = ast.newMethodInvocation();
    methodInvocation1.setName(ast.newSimpleName("getBEContext"));
    methodInvocation.setExpression(methodInvocation1);

    block.statements().add(ast.newExpressionStatement(methodInvocation));
  }

  private void buildNewActionInfo(Block block) {
    VariableDeclarationFragment variableDeclarationFragment = ast.newVariableDeclarationFragment();
    variableDeclarationFragment.setName(ast.newSimpleName("val"));

    ClassInstanceCreation classInstanceCreation = ast.newClassInstanceCreation();
    classInstanceCreation.setType(ast.newSimpleType(ast.newName(method.getClassName())));

    MethodInvocation methodInvocationGetBeContext = ast.newMethodInvocation();
    methodInvocationGetBeContext.setName(ast.newSimpleName("getBEContext"));
    classInstanceCreation.arguments().add(methodInvocationGetBeContext);

    for (int i = 0; i < method.getBeParams().getCount(); i++) {
      BEMethodParameter methodParameter = method.getBeParams().getItem(i);
      classInstanceCreation.arguments().add(ast.newSimpleName(methodParameter.getParamCode()));
    }

    variableDeclarationFragment.setInitializer(classInstanceCreation);
    VariableDeclarationStatement variableDeclarationStatement =
        ast.newVariableDeclarationStatement(variableDeclarationFragment);
    variableDeclarationStatement.setType(
        ast.newSimpleType(ast.newName(method.getClassName())));
    block.statements().add(variableDeclarationStatement);
  }

  private void buildExecuteInfo(Block block) {
    MethodInvocation methodInvocation = ast.newMethodInvocation();
    methodInvocation.setName(ast.newSimpleName("execute"));

    methodInvocation.arguments().add(ast.newSimpleName("val"));
    block.statements().add(ast.newExpressionStatement(methodInvocation));

    if (method.getReturnValue() == null
        || method.getReturnValue().getClassName().toLowerCase().contains("void")) {

    } else {
      ReturnStatement returnStatement = ast.newReturnStatement();
      MethodInvocation getResultMethod = ast.newMethodInvocation();
      getResultMethod.setName(ast.newSimpleName("getResult"));
      getResultMethod.setExpression(ast.newSimpleName("val"));
      returnStatement.setExpression(getResultMethod);
      block.statements().add(returnStatement);
    }
  }

  // TODO: be和bemanager的实现类暂时不用显示接口实现,因为运行时生成没有声明为接口.
  // protected override bool  isExplicit() { return true; }

  // protected override Type  getExplicitInterfaceType() { return
  // apiGenCtx.BEGenContext.BEInterfaceType; }

  @Override
  protected void doInitialize() {
    GspMetadata metadata =
        coreGenContext.getParentContext().getProjContext().getCefGenContext()
            .getMetadata(action.getComponentPkgName(), action.getComponentId());
    cmp =
        (BEComponent)
            ((metadata.getContent() instanceof BEComponent) ? metadata.getContent() : null);
    if (cmp == null) {
      throw new RuntimeException(
          /*ErrorCode.BeCompNotFound, */ Utils.formatExceptionMsg(
          "BE动作构件不存在: " + action.getComponentId()));
    }
    method = cmp.getBeMethod();
    checkBEMethod(method);
  }

  @Override
  protected String getMethodName() {
    return action.getCode();
  }

  @Override
  protected ArrayList<ParameterInfo> getParameterCollection() {
    return preparePars();
  }

  private ArrayList<ParameterInfo> preparePars() {
    if (parList == null) {
      parList = new ArrayList<>();
      for (int i = 0; i < method.getBeParams().getCount(); i++) {
        ParameterInfo info = new ParameterInfo();
        info.setParamType(
            com.inspur.edp.cef.generator.overall.Utils
                .getNativeType(method.getBeParams().getItem(i),
                    coreGenContext.getParentContext().getProjContext()));
        info.setParamName(method.getBeParams().getItem(i).getParamCode());
        parList.add(info);
      }
    }
    return parList;
  }

  @Override
  protected TypeInfo getReturnType() {
    return com.inspur.edp.cef.generator.overall.Utils
        .getReturnType(method,
            coreGenContext.getParentContext().getProjContext().getCefGenContext());
  }

  @Override
  protected boolean getIsOverride() {
    return true;
  }

  @Override
  protected ArrayList<Modifier.ModifierKeyword> getAccessModifiers() {
    return new ArrayList<Modifier.ModifierKeyword>(
        java.util.Arrays.asList(
            Modifier.ModifierKeyword.PUBLIC_KEYWORD));
  }

  private void checkBEMethod(BEMethod method) {
    for (Object para : method.getParameterCollection()) {
      checkPara((ICompParameter) para);
    }
    checkReturnValue(method.getReturnValue());
  }

  private void checkPara(ICompParameter para) {
//		throw new RuntimeException(
//				/*"BEGen_0004", */ "业务实体["
//				+ coreGenContext.getBE().getName()
//				+ "]中的节点["
//				+ belongObject.getName()
//				+"上的实体动作["
//				+ action.getName()
//				+ "]的参数["
//				+ para.getParamName()
//				+ "]的Java类名为空,请完善.");
  }

  private void checkReturnValue(ICompParameter returnValue) {
//		throw new RuntimeException(
//				/*"BEGen_0004", */ "业务实体["
//				+ coreGenContext.getBE().getName()
//				+ "]中的节点["
//				+ belongObject.getName()
//				+ "]上的实体动作["
//				+ action.getName()
//				+ "]返回值Java类名为空,请完善.");
  }
}
